package com.fulu.game.bi.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.fulu.game.bi.common.util.math.MathUtils;
import com.fulu.game.bi.entity.bo.channel.DictItemBO;
import com.fulu.game.bi.entity.po.DictItem;
import com.fulu.game.bi.entity.po.roi.NewUserRealtimeStat;
import com.fulu.game.bi.entity.vo.market.TodayRealtimeStatDisplayVO;
import com.fulu.game.bi.entity.vo.play.GameOverviewRealtimeVO;
import com.fulu.game.bi.entity.vo.room.RoomStatAllUserDayRealTimeVO;
import com.fulu.game.bi.mysql.bi.DictItemDao;
import com.fulu.game.bi.redis.service.market.NewAddUserService;
import com.fulu.game.bi.redis.service.market.TodayRealtimeStatService;
import com.fulu.game.bi.redis.service.play.GameOverviewService;
import com.fulu.game.bi.service.impl.CheckDataServiceImpl;
import com.fulu.game.bi.service.impl.room.VoiceOverviewService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
@Slf4j
public class DataWarnTask {
    /**
     * 【新增】：数据总览/今日实时；市场/增长-新增用户；语音互动/业务总览；游戏陪玩/业务总览   实时数据10分钟未更新钉钉进行预警通知
     * 【新增】：数据总览/历史趋势 ；市场/增长；语音互动；游戏陪玩；增值业务 离线数据 每天早上8点检测昨日数据是否更新，未更新时进行钉钉预警通知
     */
    private static final String URL = "https://oapi.dingtalk.com/robot/send?access_token=61ce19338172f5650e3da91d5e2b3103e8109d4c0ddd16ee9fd263298da4bd75";
    private static final String SECRET = "SEC49dbeae4706d026e63c9e25fbdc99584e0e4daa562fdfa753a0aa47fe6fc7fc5";
    private static final String TEMPLATE = "{\"msgtype\":\"text\",\"text\":{\"content\":\"%s\"},\"at\":{\"atMobiles\":[\"13477039331\"],\"isAtAll\":false}}";
    private static Map<String, Object> dataMap = new HashMap<>();

    private static final String CHECK_DATA = "CHECK_DATA";
    private static final String SWITCH = "SWITCH";
    private static final String RATIO = "RATIO";

    @Autowired
    private TodayRealtimeStatService todayRealtimeStatService;
    @Autowired
    private NewAddUserService newAddUserService;
    @Autowired
    private VoiceOverviewService voiceOverviewService;
    @Autowired
    private GameOverviewService gameOverviewService;
    @Autowired
    private CheckDataServiceImpl checkDataService;
    @Autowired
    private DictItemDao dictItemDao;

    @Scheduled(cron = "0 0/10 * * * ? ")
    public void realtime() {
        if (!isOpen()) {
            return;
        }
        List<String> name = new ArrayList<>();
        //数据总览/今日实时
        TodayRealtimeStatDisplayVO todayReal = todayRealtimeStatService.today();
        if (Objects.equals(JSON.toJSONString(dataMap.get("todayReal")), JSON.toJSONString(todayReal))) {
            name.add("《数据总览/今日实时》");
        }
        dataMap.put("todayReal", todayReal);
        //市场/增长-新增用户
        NewUserRealtimeStat addUser = newAddUserService.newUserRealtimeStat();
        if (Objects.equals(JSON.toJSONString(dataMap.get("addUser")), JSON.toJSONString(addUser))) {
            name.add("《市场/增长-新增用户》");
        }
        dataMap.put("addUser", addUser);
        //语音互动/业务总览
        List<RoomStatAllUserDayRealTimeVO> voice = voiceOverviewService.overviewRealTime();
        if (Objects.equals(JSON.toJSONString(dataMap.get("voice")), JSON.toJSONString(voice))) {
            name.add("《语音互动/业务总览》");
        }
        dataMap.put("voice", voice);
        //游戏陪玩/业务总览
        List<GameOverviewRealtimeVO> gamePlay = gameOverviewService.realtime();
        if (Objects.equals(JSON.toJSONString(dataMap.get("gamePlay")), JSON.toJSONString(gamePlay))) {
            name.add("《游戏陪玩/业务总览》");
        }
        dataMap.put("gamePlay", gamePlay);
        if (CollectionUtil.isNotEmpty(name)) {
            pushMsg(name.toString() + "10分钟未更新 @13477039331");
        }
    }

    @Scheduled(cron = "0 0 8 * * ? ")
    public void daily() {
        if (!isOpen()) {
            return;
        }
        List<String> name = new ArrayList<>();
        String ratio = getRatio();
        List<String> tableNames = checkDataService.tableName();
        tableNames = tableNames.stream().filter(map -> map.contains("_")).filter(map -> !map.contains("realtime")).collect(Collectors.toList());
        tableNames.stream().filter(map -> map.contains("day")).forEach(tableName -> {
            String yesterday = getStatDate(tableName, DateUtil.offsetDay(new Date(), -1));
            Integer yesterdayCount = checkDataService.count(yesterday, tableName);
            String dayBeforeYesterday = getStatDate(tableName, DateUtil.offsetDay(new Date(), -2));
            Integer dayBeforeYesterdayCount = checkDataService.count(dayBeforeYesterday, tableName);
            if (MathUtils.ratio(yesterdayCount, dayBeforeYesterdayCount).compareTo(new BigDecimal(ratio)) < 0) {
                name.add(tableName);
            }
            log.info("day table:{},yesterday:{},dayBeforeYesterday:{}", tableName, yesterdayCount, dayBeforeYesterdayCount);
        });
        tableNames.stream().filter(map -> map.contains("week")).forEach(tableName -> {
            String yesterday = getStatDate(tableName, DateUtil.beginOfWeek(DateUtil.offsetDay(new Date(), -7)));
            Integer yesterdayCount = checkDataService.count(yesterday, tableName);
            String dayBeforeYesterday = getStatDate(tableName, DateUtil.beginOfWeek(DateUtil.offsetDay(new Date(), -14)));
            Integer dayBeforeYesterdayCount = checkDataService.count(dayBeforeYesterday, tableName);
            if (MathUtils.ratio(yesterdayCount, dayBeforeYesterdayCount).compareTo(new BigDecimal(ratio)) < 0) {
                name.add(tableName);
            }
            log.info("week table:{},yesterday:{},dayBeforeYesterday:{}", tableName, yesterdayCount, dayBeforeYesterdayCount);
        });
        tableNames.stream().filter(map -> map.contains("month")).forEach(tableName -> {
            String lastMonth = getStatDate(tableName, DateUtil.offsetMonth(new Date(), -1));
            Integer lastMonthCount = checkDataService.count(lastMonth, tableName);
            String theMonthBeforeLast = getStatDate(tableName, DateUtil.offsetMonth(new Date(), -2));
            Integer theMonthBeforeLastCount = checkDataService.count(theMonthBeforeLast, tableName);
            if (MathUtils.ratio(lastMonthCount, theMonthBeforeLastCount).compareTo(new BigDecimal(ratio)) < 0) {
                name.add(tableName);
            }
            log.info("month table:{},lastMonth:{},theMonthBeforeLast:{}", tableName, lastMonthCount, theMonthBeforeLastCount);
        });
        if (CollectionUtil.isNotEmpty(name)) {
            pushMsg(name.toString() + " 数据差距较大 @13477039331");
        }
    }

    private String getRatio() {
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setDictCode(CHECK_DATA);
        dictItemBO.setCode(RATIO);
        List<DictItem> list = dictItemDao.findByParameter(dictItemBO);
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0).getVal();
        }
        return "0";
    }

    public String getStatDate(String table, Date date) {
        String dateStr;
        if (table.contains("month")) {
            dateStr = DateUtil.format(date, "yyyy-MM");
        } else {
            dateStr = DateUtil.formatDate(date);
        }
        return dateStr;
    }

    private boolean isOpen() {
        DictItemBO dictItemBO = new DictItemBO();
        dictItemBO.setDictCode(CHECK_DATA);
        dictItemBO.setCode(SWITCH);
        List<DictItem> list = dictItemDao.findByParameter(dictItemBO);
        return CollectionUtil.isNotEmpty(list) && Objects.equals(list.get(0).getVal(), "1");
    }

    private void pushMsg(String msg) {
        try {
            Long timestamp = System.currentTimeMillis();
            String stringToSign = timestamp + "\n" + SECRET;
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(SECRET.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
            String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
            HttpUtil.createPost(URL + "&timestamp=" + timestamp + "&sign=" + sign)
                    .body(String.format(TEMPLATE, msg)).timeout(20000).execute();
            log.info("消息发送成功{}", msg);
        } catch (Exception e) {
            log.error("推送钉钉消息异常", e);
        }
    }

}
